package org.roger.index;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.shape.Shape;
import org.roger.search.CustomScoreSearch;

/**
 * 建立空间索引
 * @author luoweiyi
 */
public class SpatialLuceneIndex {

	private final String latField = "lat";
	private final String lngField = "lng";

	private SpatialStrategy strategy;
	private String indexPath;
	private SpatialContext ctx;
	private Directory directory;

	public SpatialLuceneIndex(String indexPath) {
		this.indexPath = indexPath;
	}

	protected void init() {
		// Typical geospatial context
		// These can also be constructed from SpatialContextFactory
		this.ctx = SpatialContext.GEO;
		int maxLevels = 11;// results in sub-meter precision for geohash
		SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
		this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");
		try {
			this.directory = FSDirectory.open(Paths.get(indexPath));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// protected void init() {
	// //Typical geospatial context
	// //These can also be constructed from SpatialContextFactory
	// this.ctx = SpatialContext.GEO;
	// int maxLevels = 11;//results in sub-meter precision for geohash
	// SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
	// this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");
	// try {
	// this.directory = FSDirectory.open(new File(indexPath));
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// }

	public void index() throws IOException {
		init();
		createIndex();
	}

	private void createIndex() throws IOException {
		IndexWriterConfig iwConfig = new IndexWriterConfig(new SimpleAnalyzer());
		IndexWriter indexWriter = new IndexWriter(directory, iwConfig);
		// Spatial4j is x-y order for arguments|对于参数的顺序是Longitude,Latitude
		indexWriter.addDocument(newSampleDocument(0, "一星大饭店", ctx.makePoint(116.430360, 39.939686)));
		indexWriter.addDocument(newSampleDocument(1, "二星大饭店", ctx.makePoint(116.430319, 39.939702)));
		indexWriter.addDocument(newSampleDocument(2, "三星大饭店", ctx.makePoint(116.430459, 39.939802)));
		indexWriter.addDocument(newSampleDocument(3, "四星大饭店", ctx.makePoint(116.430449, 39.939902)));
		indexWriter.addDocument(newSampleDocument(4, "六星大饭店", ctx.makePoint(116.430439, 39.93402)));
		indexWriter.addDocument(newSampleDocument(5, "七星大饭店", ctx.makePoint(116.430419, 39.934102)));
		indexWriter.addDocument(newSampleDocument(6, "五星大饭店", ctx.makePoint(116.430429, 39.934202)));
		indexWriter.addDocument(newSampleDocument(6, "五星大酒店", ctx.makePoint(115.430429, 39.934202)));
		indexWriter.commit();
		indexWriter.close();
	}

	private Document newSampleDocument(int id, String keyword, Shape... shapes) {
		Document doc = new Document();
		doc.add(new IntPoint("id", id));
		// Potentially more than one shape in this field is supported by some
		// strategies; see the javadocs of the SpatialStrategy impl to see.
		for (Shape shape : shapes) {
			for (IndexableField f : strategy.createIndexableFields(shape)) {
				doc.add(f);
			}
			// store it too; the format is up to you
			doc.add(new StoredField(strategy.getFieldName(), ctx.toString(shape)));
		}
		doc.add(new StringField("keyword", keyword, Field.Store.YES));
		return doc;
	}

	public static void main(String[] args) {
		/*File file = new File("D:/tmp/lucene/spatial");
		if (!file.exists()) {
			file.mkdirs();
		}*/
		SpatialLuceneIndex index = new SpatialLuceneIndex("D:/tmp/lucene/spatial");
		try {
			index.index();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
